﻿/*
 * KLF Headless Browser
 * Written by Kris Oye <kristianoye@gmail.com>
 * Copyright (C) 2011-2012.  All rights reserved.
 */
namespace KLF.Lib.Browser.DOM.HTML
{
    #region Using Statements

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    #endregion

    public class HTMLOptionElement : HTMLControlBase
    {
        #region Constructors

        internal HTMLOptionElement(Document owner) 
            : base(owner, HTMLConstants.HTML_TAG_OPTION)
        {
        }

        public HTMLOptionElement(string displayValue, string optionValue, bool selected)
            : base(null, HTMLConstants.HTML_TAG_OPTION)
        {
        }

        #endregion

        #region DOM Level 2 HTML Compliance

        /// <summary>
        /// Represents the value of the HTML selected attribute. The value of
        /// this attribute does not change if the state of the corresponding 
        /// form control, in an interactive user agent, changes. See the 
        /// selected attribute definition in HTML 4.01.
        /// </summary>
        public bool defaultSelected
        {
            get
            {
                return getAttribute("defaultSelected").Equals(HTMLConstants.HTML_ATT_SELECTED);
            }
            set
            {
                setAttribute("defaultSelected", value ? HTMLConstants.HTML_ATT_SELECTED : "not-selected");
            }
        }

        /// <summary>
        /// The index of this OPTION in its parent SELECT, starting from 0.
        /// </summary>
        public int index
        {
            get
            {
                List<HTMLOptionElement> opts = selectControl.Options;
                return opts.IndexOf(this);
            }
        }

        /// <summary>
        /// Option label for use in hierarchical menus. See the label attribute 
        /// definition in HTML 4.01.
        /// </summary>
        public string label
        {
            get
            {
                return getAttribute(HTMLConstants.HTML_ATT_LABEL);
            }
            set
            {
                setAttribute(HTMLConstants.HTML_ATT_LABEL, value);
            }
        }

        /// <summary>
        /// Non-standard helper function to get the SELECT object
        /// that owns this option.  Returns null if not attached.
        /// </summary>
        public HTMLSelectElement selectControl
        {
            get
            {
                Node p = Parent;
                do
                {
                    if (p != null && (p as HTMLSelectElement) != null)
                        break;
                    p = p.Parent;
                }
                while (p != null);

                return (p as HTMLSelectElement);
            }
        }

        /// <summary>
        /// Represents the current state of the corresponding form control, in
        /// an interactive user agent. Changing this attribute changes the 
        /// state of the form control, but does not change the value of the 
        /// HTML selected attribute of the element.
        /// </summary>
        public bool selected
        {
            get
            {
                bool result = HTMLBool.Eval(
                    getAttribute(HTMLConstants.HTML_ATT_SELECTED),
                    HTMLConstants.HTML_ATT_SELECTED);

                if (selectControl.multiple)
                    return result;

                if (result || selectControl == null)
                    return result;

                return (result = (this == selectControl.selectedItem));
            }
            set
            {
                HTMLSelectElement s = selectControl;

                if (s.multiple || s == null)
                {
                    if (!value)
                        removeAttribute(HTMLConstants.HTML_ATT_SELECTED);
                    else
                    {
                        setAttribute(
                            HTMLConstants.HTML_ATT_SELECTED,
                            HTMLConstants.HTML_ATT_SELECTED);
                    }
                }
                else
                {
                    foreach (HTMLElement o in s.Options)
                    {
                        if (o != this || !value)
                            o.removeAttribute(HTMLConstants.HTML_ATT_SELECTED);
                        else if (o == this && value)
                        {
                            o.setAttribute(HTMLConstants.HTML_ATT_SELECTED,
                                HTMLConstants.HTML_ATT_SELECTED);
                            s.selectedItem = this;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// The text contained within the option element.
        /// </summary>
        public string text
        {
            get
            {
                return textContent;
            }
            set
            {
                textContent = value;
            }
        }

        #endregion
    }
}
